package org.kosmix.kosmosfs.access;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Properties;

public class KfsAccess {
	private long cPtr;

	private static final native long initF(String paramString);

	private static final native long initS(String paramString, int paramInt);

	private static final native int cd(long paramLong, String paramString);

	private static final native int mkdirs(long paramLong, String paramString);

	private static final native int rmdir(long paramLong, String paramString);

	private static final native int rmdirs(long paramLong, String paramString);

	private static final native String[] readdir(long paramLong,
			String paramString, boolean paramBoolean);

	private static final native String[] readdirplus(long paramLong,
			String paramString);

	private static final native String[][] getDataLocation(long paramLong1,
			String paramString, long paramLong2, long paramLong3);

	private static final native short getReplication(long paramLong,
			String paramString);

	private static final native short setReplication(long paramLong,
			String paramString, int paramInt);

	private static final native long getModificationTime(long paramLong,
			String paramString);

	private static final native int create(long paramLong, String paramString,
			int paramInt, boolean paramBoolean);

	private static final native int remove(long paramLong, String paramString);

	private static final native int rename(long paramLong, String paramString1,
			String paramString2, boolean paramBoolean);

	private static final native int open(long paramLong, String paramString1,
			String paramString2, int paramInt);

	private static final native int exists(long paramLong, String paramString);

	private static final native int isFile(long paramLong, String paramString);

	private static final native int isDirectory(long paramLong,
			String paramString);

	private static final native long filesize(long paramLong, String paramString);

	public KfsAccess(String configFn) throws IOException {
		this.cPtr = initF(configFn);
		if (this.cPtr == 0L)
			throw new IOException("Unable to initialize KFS Client");
	}

	public KfsAccess(String metaServerHost, int metaServerPort)
			throws IOException {
		this.cPtr = initS(metaServerHost, metaServerPort);
		if (this.cPtr == 0L)
			throw new IOException("Unable to initialize KFS Client");
	}

	public int kfs_cd(String path) {
		return cd(this.cPtr, path);
	}

	public int kfs_mkdirs(String path) {
		return mkdirs(this.cPtr, path);
	}

	public int kfs_rmdir(String path) {
		return rmdir(this.cPtr, path);
	}

	public int kfs_rmdirs(String path) {
		return rmdirs(this.cPtr, path);
	}

	public String[] kfs_readdir(String path) {
		return kfs_readdir(path, false);
	}

	public String[] kfs_readdir(String path, boolean prefetchAttr) {
		return readdir(this.cPtr, path, prefetchAttr);
	}

	public KfsFileAttr[] kfs_readdirplus(String path) {
		String[] entries = readdirplus(this.cPtr, path);
		if (entries == null) {
			return null;
		}
		KfsFileAttr[] fattr = new KfsFileAttr[entries.length];

		for (int i = 0; i < entries.length; i++) {
			byte[] arr = entries[i].getBytes();
			ByteArrayInputStream bis = new ByteArrayInputStream(arr);
			Properties prop = new Properties();
			try {
				prop.load(bis);
				fattr[i] = new KfsFileAttr();

				fattr[i].filename = prop.getProperty("Filename", "");
				String s = prop.getProperty("IsDirectory", "false");
				if (s.startsWith("true"))
					fattr[i].isDirectory = true;
				else {
					fattr[i].isDirectory = false;
				}
				s = prop.getProperty("Filesize", "0");
				fattr[i].filesize = Long.parseLong(s);

				s = prop.getProperty("M-Time", "0");
				fattr[i].modificationTime = Long.parseLong(s);

				s = prop.getProperty("Replicas", "1");
				fattr[i].replication = Integer.parseInt(s);
			} catch (Exception e) {
				e.printStackTrace();
				fattr[i] = null;
			}
		}
		return fattr;
	}

	public KfsOutputChannel kfs_append(String path) {
		int fd = open(this.cPtr, path, "a", 1);
		if (fd < 0)
			return null;
		return new KfsOutputChannel(this.cPtr, fd);
	}

	public KfsOutputChannel kfs_create(String path) {
		return kfs_create(path, 1);
	}

	public KfsOutputChannel kfs_create(String path, int numReplicas) {
		return kfs_create(path, numReplicas, false);
	}

	public KfsOutputChannel kfs_create(String path, int numReplicas,
			boolean exclusive) {
		int fd = create(this.cPtr, path, numReplicas, exclusive);
		if (fd < 0)
			return null;
		return new KfsOutputChannel(this.cPtr, fd);
	}

	public KfsInputChannel kfs_open(String path) {
		int fd = open(this.cPtr, path, "r", 1);
		if (fd < 0)
			return null;
		return new KfsInputChannel(this.cPtr, fd);
	}

	public int kfs_remove(String path) {
		return remove(this.cPtr, path);
	}

	public int kfs_rename(String oldpath, String newpath) {
		return rename(this.cPtr, oldpath, newpath, true);
	}

	public int kfs_rename(String oldpath, String newpath, boolean overwrite) {
		return rename(this.cPtr, oldpath, newpath, overwrite);
	}

	public boolean kfs_exists(String path) {
		return exists(this.cPtr, path) == 1;
	}

	public boolean kfs_isFile(String path) {
		return isFile(this.cPtr, path) == 1;
	}

	public boolean kfs_isDirectory(String path) {
		return isDirectory(this.cPtr, path) == 1;
	}

	public long kfs_filesize(String path) {
		return filesize(this.cPtr, path);
	}

	public String[][] kfs_getDataLocation(String path, long start, long len) {
		return getDataLocation(this.cPtr, path, start, len);
	}

	public short kfs_getReplication(String path) {
		return getReplication(this.cPtr, path);
	}

	public short kfs_setReplication(String path, int numReplicas) {
		return setReplication(this.cPtr, path, numReplicas);
	}

	public long kfs_getModificationTime(String path) {
		return getModificationTime(this.cPtr, path);
	}

	protected void finalize() throws Throwable {
		release();
		super.finalize();
	}

	public void release() {
		if (this.cPtr != 0L)
			;
	}

	static {
		try {
			System.loadLibrary("kfs_access");
		} catch (UnsatisfiedLinkError e) {
			e.printStackTrace();
			System.err.println("Unable to load kfs_access native library: "
					+ System.getProperty("java.library.path"));
			System.exit(1);
		}
	}
}